#pragma once

#include "comm/znx_pool.h"
#include "comm/znx_queue.h"
#include "comm/znx_string.h"


typedef int(*znx_http_arg_cmp_handle)(znx_str_t *a, znx_str_t *b);


typedef struct {
    znx_str_t                   key;
    znx_str_t                   val;
    znx_queue_t                 queue;

    /* if value not empty, the has_delimiter flag will be ignore. */
    unsigned                    has_delimiter:1;
} znx_http_arg_t;


typedef struct {
    znx_queue_t                 head;
    znx_http_arg_cmp_handle     cmp_handle;
} znx_http_args_t;


static inline int
znx_http_arg_cmp(znx_str_t *a, znx_str_t *b)
{
    if (a->len > b->len) {
        return 1;
    }

    if (a->len < b->len) {
        return -1;
    }

    return znx_strncmp(a->data, b->data, a->len);
}


static inline void
znx_http_args_init(znx_http_args_t *args)
{
    znx_queue_init(&args->head);
    args->cmp_handle = znx_http_arg_cmp;
}


// add the arg to the tail of the queue.
void znx_http_args_add(znx_http_args_t *args, znx_http_arg_t *arg);


// use the arg to cover all same args.
// if no arg with the same name exits, will add the arg to the tailf of the queue.
void znx_http_args_set(znx_http_args_t *args, znx_http_arg_t *arg);


// get the i-th header with the same name.
// to get the first header, just pass in 0.
znx_http_arg_t *znx_http_args_get(znx_http_args_t *args, znx_str_t *key, size_t index);


// delete the first matching arg.
void znx_http_args_del_once(znx_http_args_t *args, znx_str_t *key);


// delete all matching args.
void znx_http_args_del(znx_http_args_t *args, znx_str_t *key);


// parser args str to http_args
// supports string parsing in the following format.
// 1. ""            ==> {}
// 2. "a"           ==> {"a": ""}
// 3. "a="          ==> {"a": ""}
// 4. "=1"          ==> {"": "1"}
// 5. "a=&b=1"      ==> {"a": "", "b": "1"}
// 6. "a&b=1"       ==> {"a": "", "b": "1"}
// 7. "=1&b=1"      ==> {"": "1", "b": "1"}
// 8. "&b=1"        ==> {"": "",  "b": "1"}
// 9. "&&b=1"       ==> {"": "",  "": "",  "b": "1"}
void znx_http_args_parse(znx_pool_t *pool, znx_http_args_t *args, znx_str_t *args_str);


// real data space is apploed from the pool.
void znx_http_args_to_string(znx_pool_t *pool, znx_http_args_t *args, znx_str_t *dst_str);
